home *** CD-ROM | disk | FTP | other *** search
- /* popen.c -- popen/pclose for OS/2. */
-
- /* Set to 0 for distribution.
- Search for "DIAGNOSTIC" in the code to see what it's for. */
- #define DIAGNOSTIC 0
-
- #define INCL_DOSQUEUES
- #define INCL_DOSPROCESS
- #define INCL_DOSSESMGR
- #include <os2.h>
- #include <process.h>
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctype.h>
- #include <string.h>
- #include <fcntl.h>
-
- #define LL_VAL ULONG
- #define LL_KEY PID /* also ULONG, really */
-
-
- #define STDIN 0
- #define STDOUT 1
- #define STDERR 2
-
- /* ********************************************************************* *
- * *
- * First, a little linked-list library to help keep track of pipes: *
- * *
- * ********************************************************************* */
-
- /* Map integer PID's onto integer termination codes. */
- struct pid_list
- {
- HFILE pid; /* key */
- ULONG term_code; /* val */
- struct pid_list *next; /* duh */
- };
-
- static struct pid_list *pid_ll = (struct pid_list *) NULL;
-
- /* The ll_*() functions all make use of the global var `pid_ll'. */
-
- void
- ll_insert (HFILE key, ULONG val)
- {
- struct pid_list *new;
- new = (struct pid_list *) malloc (sizeof (*new));
-
- new->pid = key;
- new->term_code = val;
- new->next = pid_ll;
-
- pid_ll = new;
- }
-
-
- void
- ll_delete (int key)
- {
- struct pid_list *this, *last;
-
- this = pid_ll;
- last = (struct pid_list *) NULL;
-
- while (this)
- {
- if (this->pid == key)
- {
- /* Delete this node and leave. */
- if (last)
- last->next = this->next;
- else
- pid_ll = this->next;
- free (this);
- return;
- }
-
- /* Else no match, so try the next one. */
- last = this;
- this = this->next;
- }
- }
-
- ULONG
- ll_lookup (HFILE key)
- {
- struct pid_list *this = pid_ll;
-
- while (this)
- {
- if (this->pid == key)
- return this->term_code;
-
- /* Else no match, so try the next one. */
- this = this->next;
- }
-
- /* Zero is special in this context anyway. */
- return 0;
- }
-
- #if DIAGNOSTIC
- ULONG
- ll_length ()
- {
- struct pid_list *this = pid_ll;
- unsigned long int len;
-
- for (len = 0; this; len++)
- this = this->next;
-
- return len;
- }
-
- ULONG
- ll_print ()
- {
- struct pid_list *this = pid_ll;
- unsigned long int i;
-
- for (i = 0; this; i++)
- {
- printf ("pid_ll[%d] == (%5d --> %5d)\n",
- i, this->pid, this->term_code);
- this = this->next;
- }
-
- if (i == 0)
- printf ("No entries.\n");
-
- return i;
- }
- #endif /* DIAGNOSTIC */
-
- /* ********************************************************************* *
- * *
- * End of linked-list library, beginning of popen/pclose: *
- * *
- * ********************************************************************* */
-
- /*
- * Routine: popen
- * Returns: FILE pointer to pipe.
- * Action : Exec program connected via pipe, connect a FILE * to the
- * pipe and return it.
- * Params : Command - Program to run
- * Mode - Mode to open pipe. "r" implies pipe is connected
- * to the programs stdout, "w" connects to stdin.
- */
- FILE *
- popen (const char *Command, const char *Mode)
- {
- HFILE End1, End2, Std, Old1, Old2, Tmp;
-
- FILE *File;
-
- char Fail[256],
- *Args,
- CmdLine[256],
- *CmdExe;
-
- RESULTCODES
- Result;
-
- int Rc;
-
- if (DosCreatePipe (&End1, &End2, 4096))
- return NULL;
-
- Std = (*Mode == 'w') ? STDIN : STDOUT ;
- if (Std == STDIN)
- {
- Tmp = End1; End1 = End2; End2 = Tmp;
- }
-
- Old1 = -1; /* save stdin or stdout */
- DosDupHandle (Std, &Old1);
- DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
- Tmp = Std; /* redirect stdin or stdout */
- DosDupHandle (End2, &Tmp);
-
- if (Std == 1)
- {
- Old2 = -1; /* save stderr */
- DosDupHandle (STDERR, &Old2);
- DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
- Tmp = STDERR;
- DosDupHandle (End2, &Tmp);
- }
-
- DosClose (End2);
- DosSetFHState (End1, OPEN_FLAGS_NOINHERIT);
-
- if ((CmdExe = getenv ("COMSPEC")) == NULL )
- CmdExe = "cmd.exe";
-
- strcpy (CmdLine, CmdExe);
- Args = CmdLine + strlen (CmdLine) + 1; /* skip zero */
- strcpy (Args, "/c ");
- strcat (Args, Command);
- Args[strlen (Args) + 1] = '\0'; /* two zeroes */
- Rc = DosExecPgm (Fail, sizeof (Fail), EXEC_ASYNCRESULT,
- (unsigned char *) CmdLine, 0, &Result,
- (unsigned char *) CmdExe);
-
- Tmp = Std; /* restore stdin or stdout */
- DosDupHandle (Old1, &Tmp);
- DosClose (Old1);
-
- if (Std == STDOUT)
- {
- Tmp = STDERR; /* restore stderr */
- DosDupHandle (Old2, &Tmp);
- DosClose (Old2);
- }
-
- if (Rc)
- {
- DosClose (End1);
- return NULL;
- }
-
- File = fdopen (End1, Mode);
- ll_insert ((LL_KEY) End1, (LL_VAL) Result.codeTerminate);
-
- return File;
- }
-
-
- /*
- * Routine: popenRW
- * Returns: PID of child process
- * Action : Exec program connected via pipe, connect int fd's to
- * both the stdin and stdout of the process.
- * Params : Command - Program to run
- * Pipes - Array of 2 ints to store the pipe descriptors
- * Pipe[0] writes to child's stdin,
- * Pipe[1] reads from child's stdout/stderr
- */
- int
- popenRW (const char **argv, int *pipes)
- {
- HFILE Out1, Out2, In1, In2;
- HFILE Old0 = -1, Old1 = -1, Old2 = -1, Tmp;
-
- PID pid;
-
- if (DosCreatePipe (&Out2, &Out1, 4096))
- return FALSE;
-
- if (DosCreatePipe (&In1, &In2, 4096))
- {
- DosClose (Out1);
- DosClose (Out2);
- return FALSE;
- }
-
- /* Save std{in,out,err} */
- DosDupHandle (STDIN, &Old0);
- DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
- DosDupHandle (STDOUT, &Old1);
- DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
- DosDupHandle (STDERR, &Old2);
- DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
-
- /* Redirect std{in,out,err} */
- Tmp = STDIN;
- DosDupHandle (In1, &Tmp);
- Tmp = STDOUT;
- DosDupHandle (Out1, &Tmp);
- Tmp = STDERR;
- DosDupHandle (Out1, &Tmp);
-
- /* Close file handles not needed in child */
-
- DosClose (In1);
- DosClose (Out1);
- DosSetFHState (In2, OPEN_FLAGS_NOINHERIT);
- DosSetFHState (Out2, OPEN_FLAGS_NOINHERIT);
-
- /* Spawn we now our hoary brood. */
- pid = spawnvp (P_NOWAIT, argv[0], argv);
-
- /* Restore std{in,out,err} */
- Tmp = STDIN;
- DosDupHandle (Old0, &Tmp);
- DosClose (Old0);
- Tmp = STDOUT;
- DosDupHandle (Old1, &Tmp);
- DosClose (Old1);
- Tmp = STDERR;
- DosDupHandle (Old2, &Tmp);
- DosClose (Old2);
-
- if(pid < 0)
- {
- DosClose (In2);
- DosClose (Out2);
- return -1;
- }
-
- pipes[0] = In2;
- _setmode (pipes[0], O_BINARY);
- pipes[1] = Out2;
- _setmode (pipes[1], O_BINARY);
-
- /* Save ID of write-to-child pipe for pclose() */
- ll_insert ((LL_KEY) In2, (LL_VAL) pid);
-
- return pid;
- }
-
-
- /*
- * Routine: pclose
- * Returns: TRUE on success
- * Action : Close a pipe opened with popen();
- * Params : Pipe - pipe to close
- */
- int
- pclose (FILE *Pipe)
- {
- RESULTCODES rc;
- PID pid, pid1;
- int Handle = fileno (Pipe);
-
- fclose (Pipe);
-
- rc.codeTerminate = -1;
-
- pid1 = (PID) ll_lookup ((LL_KEY) Handle);
- /* if pid1 is zero, something's seriously wrong */
- if (pid1 != 0)
- {
- DosWaitChild (DCWA_PROCESSTREE, DCWW_WAIT, &rc, &pid, pid1);
- ll_delete ((LL_KEY) Handle);
- }
- return rc.codeTerminate == 0 ? rc.codeResult : -1;
- }
-
-
- #if DIAGNOSTIC
- void
- main ()
- {
- FILE *fp1, *fp2, *fp3;
- int c;
-
- ll_print ();
- fp1 = popen ("gcc --version", "r");
- ll_print ();
- fp2 = popen ("link386 /?", "r");
- ll_print ();
- fp3 = popen ("dir", "r");
- ll_print ();
-
- while ((c = getc (fp1)) != EOF)
- printf ("%c", c);
-
- while ((c = getc (fp2)) != EOF)
- printf ("%c", c);
-
- while ((c = getc (fp3)) != EOF)
- printf ("%c", c);
-
- pclose (fp1);
- ll_print ();
- pclose (fp2);
- ll_print ();
- pclose (fp3);
- ll_print ();
-
- return;
- }
-
- #endif /* DIAGNOSTIC */
-